package Server;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;


import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.List;



public class MyTable extends JPanel implements TableModelListener {
	
	private MyTableModel myModel;
	private JTable myTable;
	private JLabel lblName;
	private String backUpData;
	
	public MyTable(int a, int b,List<Object[]> data , List<String> names, List<String> types,String name,List<Boolean> khoa)
	{
		super (new BorderLayout());
		myModel = new MyTableModel(data,names,types,name,khoa);
		myTable = new JTable(myModel);
		lblName = new JLabel(name);
		myModel.addTableModelListener(this);
		
		myTable.getSelectionModel().addListSelectionListener(new RowListener());		// Lắng nghe row được chọn
		myTable.getColumnModel().getSelectionModel().addListSelectionListener(new ColumnListener());	// Lắng nghe column được chọn
		
		myTable.setPreferredScrollableViewportSize(new Dimension(a,b));
		myTable.setFillsViewportHeight(true);
		myTable.setPreferredSize(new Dimension(0,10000));

		// Create the scroll pane and add the table to it.
		JScrollPane scrollPane = new JScrollPane(myTable);
		add(lblName,BorderLayout.PAGE_START);
		add(scrollPane,BorderLayout.CENTER);
	}


	public MyTableModel layMyModel() {
		return myModel;
	}

	public JTable layBang() {
		return myTable;
	} 
	
	public void themDong(Object[] newRow) {
		if (myModel != null) {
			myModel.addRow(newRow);
		} else {

		}
	}
	
	public void xoaDongCuoi() {
		if (myModel != null) {
			myModel.delete();
		} else {

		}
	}
	public void xoaDong(int row){
		if (myModel != null) {
			myModel.deleteRow(row);
		} else {

		}
	}
	public int laySoCot()
	{
		return myModel.getColumnCount();
	}
	public int laySoDong()
	{
		return myModel.getRowCount();
	}
	public List<Boolean> layDanhSachKhoaChinh()
	{
		return myModel.getKhoaChinh();
	}
	public List<Object[]> layDanhSachDuLieu(){
		return myModel.getData();
	}
	public List<String> layDanhSachKieuDuLieu(){
		return myModel.getTypeData();
	}
	public List<String> layDanhSachTruongDuLieu(){
		return myModel.getColumnNames();
	}
	public String layTenBang(){
		return myModel.getTableName();
	}
	
	public String layDuLieuDangDuocChon()
	{
		List<String> temp = layDanhSachTruongDuLieu();
		int temp2 = myTable.getSelectedColumn();
		return temp.get(temp2);
	}
	
	public String layKieuDuLieuDangDuocChon()
	{

		List<String> temp = layDanhSachKieuDuLieu();
		int temp2 = myTable.getSelectedColumn();
		if(temp2 == -1)
			return null;
		String temp3 = temp.get(temp2);
		return temp3;
	}
	
	public boolean laKhoaChinh()
	{
		List<Boolean> danhSach = layDanhSachKhoaChinh();
		int viTri = myTable.getSelectedColumn();
		if(viTri==-1)
			return false;
		boolean ketQua = danhSach.get(viTri);
		return ketQua;
	}
	
	/**
	 * Lấy giá trị tại ô đang được chọn
	 * @return
	 */
	public Object layGiaTriDuLieuHienTai()
	{
		int cotHienTai = myTable.getSelectedColumn();
		int dongHienTai = myTable.getSelectedRow();
		
		Object temp = null;
		if (cotHienTai != -1 && dongHienTai != -1)
			temp = myTable.getValueAt(dongHienTai, cotHienTai);
		return temp;
	}
	
	/**
	 * Lấy giá trị tại vị trí (dong, cot)
	 * @return
	 */
	public Object layGiaTriDuLieuTaiViTri(int dong, int cot)
	{
		Object temp = null;
		temp = myTable.getValueAt(dong, cot);
		return temp;
	}
	
	/**
	 * Gán lại giá trị dữ liệu tại ô đang được chọn
	 */
	public void ganGiaTriTaiViTri(int dong, int cot, Object value)
	{
		if (cot != -1 && dong != -1)
		{
			myModel.setValueAt(value, dong, cot);
		}
	}
	
	/**
	 * Xử lý khi dữ liệu trong bảng có sự thay đổi, chỉnh sửa
	 */
	public void tableChanged(TableModelEvent e) throws NumberFormatException {
		if (layKieuDuLieuDangDuocChon()!= null && layKieuDuLieuDangDuocChon().equals("int"))
		{
			int value;
			String str_Value = layGiaTriDuLieuHienTai().toString();
			int dongHienTai = myTable.getSelectedRow();
			int cotHienTai = myTable.getSelectedColumn();
			
			if (str_Value.equalsIgnoreCase("null"))
				return;
			
			try
			{
				value = Integer.parseInt(str_Value);
			}
			catch (NumberFormatException s)
			{
				JOptionPane.showMessageDialog(this, "Dữ liệu vừa nhập không phù hợp kiểu int", "Lỗi nhập dữ liệu", JOptionPane.ERROR_MESSAGE);
				ganGiaTriTaiViTri(dongHienTai, cotHienTai, backUpData);			
			}
		}
		
		if (laKhoaChinh() == true)
		{
			String value = layGiaTriDuLieuHienTai().toString();
			if (value.equalsIgnoreCase("NULL") || value.isEmpty())
			{
				JOptionPane.showMessageDialog(this, "Khóa chính không được NULL hoặc trống", "Lỗi", JOptionPane.ERROR_MESSAGE);
			}
		}
	}
	
	/**
	 * Kiểm tra bảng chứa dữ liệu có hợp lệ hay không 
	 */
	public boolean kiemTraDuLieu()
	{
		int dong = laySoDong();
		int cot = laySoCot();
		
		// Kiểm tra dòng dữ liệu NULL
		boolean coItNhatMotDongNull = false;
		
		for (int i = 0 ; i < dong; i++)
		{
			boolean temp = true;
			for (int j = 0; j < cot; j++)
			{
				String giaTriHienTai = layGiaTriDuLieuTaiViTri(i, j).toString();
				if (!giaTriHienTai.equalsIgnoreCase("NULL"))
					temp = false;
			}
			if (temp == true && coItNhatMotDongNull == false)	// Phát hiện 1 dòng NULL và trước đó chưa có dòng NULL nào
			{
				coItNhatMotDongNull = true;
			}
		}
		
		if (coItNhatMotDongNull)
		{
			JOptionPane.showMessageDialog(this, "Dữ liệu không thể chứa dòng toàn NULL", "Lỗi", JOptionPane.ERROR_MESSAGE);
			return false;
		}
		
		List<Boolean> danhSachKhoaChinh = myModel.layDanhSachKhoaChinh();
		// Kiểm tra khóa chính có NULL hoặc rỗng hay không
		for (int i = 0; i < danhSachKhoaChinh.size(); i++)
		{
			// Nếu cột i là khóa chính
			if (danhSachKhoaChinh.get(i))
			{
				for (int j = 0 ; j < laySoDong(); j++)
				{
					String giaTriHienTai = layGiaTriDuLieuTaiViTri(j, i).toString();
					
					// Phát hiện có 1 cột NULL
					if (giaTriHienTai.equalsIgnoreCase("NULL") || giaTriHienTai.isEmpty())
					{
						JOptionPane.showMessageDialog(this, "Khóa chính không được NULL hoặc trống", "Lỗi", JOptionPane.ERROR_MESSAGE);
						return false;
					}
				}
			}
		}
		
		// Kiểm tra khó chính trong một cột có bị trùng nhau hay không
		if (danhSachKhoaChinh.size() > 1)
			for (int i = 0; i < danhSachKhoaChinh.size(); i++)
			{
				// Nếu cột i là khóa chính
				if (danhSachKhoaChinh.get(i))
				{
					for (int j = 0 ; j < laySoDong(); j++)
					{
						String giaTriBiSoSanh = layGiaTriDuLieuTaiViTri(j, i).toString();
						for (int k = j + 1; k < laySoDong(); k++)
						{
							String giaTriSoSanh = layGiaTriDuLieuTaiViTri(k, i).toString();
							
							// Nếu có 2 giá trị trong cột khóa chính bị trùng nhau
							if (giaTriSoSanh.equals(giaTriBiSoSanh))
							{
								JOptionPane.showMessageDialog(this, "Giá trị trong khóa chính không được trùng nhau", "Lỗi", JOptionPane.ERROR_MESSAGE);
								return false;
							}
						}
					}
				}
			}
		return true;
	}
	
	/**
	 * Lớp xử lý rows được chọn
	 * @author McDona
	 *
	 */
	public class RowListener implements ListSelectionListener {
		public void valueChanged(ListSelectionEvent event) {
			if (event.getValueIsAdjusting()) {
				return;
			}
		}
	}

	/**
	 * Xử lý column được chọn
	 * @author McDona
	 *
	 */
	public class ColumnListener implements ListSelectionListener {
		public void valueChanged(ListSelectionEvent event) {
			if (event.getValueIsAdjusting()) {
				return;
			}
			//JOptionPane.showMessageDialog(null, "COLUMN SELECTION EVENT. Dữ liệu : " + layDuLieuDangDuocChon() + "; Kiểu dữ liệu : " + layKieuDuLieuDangDuocChon());
			backUpData = layGiaTriDuLieuHienTai().toString();
		}
	}
}

